package front

import (
	"context"
	"fmt"
	"math/rand"
	"net/http"
	"shop/internal/service/product_service"
	"shop/pkg/app"
	"shop/pkg/constant"
	"shop/pkg/util"
	"strconv"
	"sync"
	"time"

	"github.com/gin-gonic/gin"
)

// user api
type TestController struct {
}

func (e *TestController) Index(c *gin.Context) {
	//fmt.Println("test index")
	var (
		appG = app.Gin{C: c}
	)
	productService := product_service.Product{
		Name:       c.Query("keyword"),
		Enabled:    1,
		PageNum:    util.GetFrontPage(c),
		PageSize:   util.GetFrontLimit(c),
		Sid:        c.Query("sid"),
		News:       c.Query("news"),
		PriceOrder: c.Query("price_order"),
		SalesOrder: c.Query("sales_order"),
	}
	vo, total, page := productService.GetTestList()

	appG.ResponsePage(http.StatusOK, constant.SUCCESS, vo, total, page)
}

// 模拟一个任务
func task(id int) int {
	// 模拟任务执行时间
	sleepTime := time.Duration(rand.Intn(100)) * time.Millisecond
	time.Sleep(sleepTime)
	fmt.Printf("任务 %d 完成，耗时 %v\n", id, sleepTime)
	return id * 2
}

// 并发任务列表接口
func (e *TestController) Bingfalist(c *gin.Context) {
	var appG = app.Gin{C: c}

	// 从请求参数获取任务数量
	numTasksStr := c.DefaultQuery("numTasks", "10")
	numTasks, err := strconv.Atoi(numTasksStr)
	if err != nil || numTasks <= 0 {
		appG.Response(http.StatusBadRequest, "参数错误", gin.H{
			"error": "numTasks 必须是正整数",
		})
		return
	}

	// 限制最大并发数，防止资源耗尽
	if numTasks > 1000 {
		numTasks = 1000
	}

	// 获取可选的并发度控制参数
	concurrencyStr := c.DefaultQuery("concurrency", "0")
	concurrency, _ := strconv.Atoi(concurrencyStr)

	results := make(chan int, numTasks)
	errorChan := make(chan error, numTasks)

	// 记录开始时间
	startTime := time.Now()

	// 方案1：使用 WaitGroup 控制所有任务完成
	if concurrency <= 0 {
		var wg sync.WaitGroup

		for i := 0; i < numTasks; i++ {
			wg.Add(1)
			go func(taskID int) {
				defer wg.Done()
				defer func() {
					if r := recover(); r != nil {
						errorChan <- fmt.Errorf("任务 %d 发生panic: %v", taskID, r)
					}
				}()

				result := task(taskID)
				results <- result
			}(i)
		}

		// 等待所有任务完成
		wg.Wait()
	} else {
		// 方案2：使用信号量控制并发度
		sem := make(chan struct{}, concurrency)
		var wg sync.WaitGroup

		for i := 0; i < numTasks; i++ {
			wg.Add(1)
			sem <- struct{}{} // 获取信号量

			go func(taskID int) {
				defer wg.Done()
				defer func() {
					<-sem // 释放信号量
					if r := recover(); r != nil {
						errorChan <- fmt.Errorf("任务 %d 发生panic: %v", taskID, r)
					}
				}()

				result := task(taskID)
				results <- result
			}(i)
		}

		wg.Wait()
	}

	close(results)
	close(errorChan)

	// 收集结果
	var successResults []int
	for result := range results {
		successResults = append(successResults, result)
	}

	// 收集错误
	var errors []string
	for err := range errorChan {
		errors = append(errors, err.Error())
	}

	// 计算总耗时
	totalTime := time.Since(startTime)

	// 返回响应
	appG.Response(http.StatusOK, "任务执行完成", gin.H{
		"total_tasks":      numTasks,
		"success_count":    len(successResults),
		"error_count":      len(errors),
		"total_time":       totalTime.String(),
		"results":          successResults,
		"errors":           errors,
		"concurrency_used": concurrency,
	})
}

func (e *TestController) BingfaOne(c *gin.Context) {
	var appG = app.Gin{C: c}

	sumtasks := c.DefaultQuery("sumtasks", "10")
	sumtasksint, err := strconv.Atoi(sumtasks)
	if err != nil {
		appG.Response(http.StatusBadRequest, "参数格式错误", nil)
		return
	}

	// 有缓冲通道 - 可以缓存指定数量的值，超过容量时才阻塞
	results := make(chan int, sumtasksint)
	//
	var wg sync.WaitGroup
	wg.Add(sumtasksint)
	for i := 0; i < sumtasksint; i++ {
		go func(sumtasksint int) {
			defer wg.Done()
			// 这里执行你的并发任务
			e.concurrentTask(sumtasksint)
			// result := task(sumtasksint)
			// results <- result
		}(i)
	}
	// 等待所有goroutine完成
	wg.Wait()
	close(results)
	appG.Response(http.StatusOK, "并发任务执行完成", gin.H{
		"total_tasks": sumtasksint,
	})
}

func (e *TestController) concurrentTask(taskNum int) {
	fmt.Println("任务", taskNum, "开始执行")
	time.Sleep(time.Second * 3)
}

func (e *TestController) BingfaTwo(c *gin.Context) {
	var appG = app.Gin{C: c}

	// 参数解析和验证
	sumtasks := c.DefaultQuery("sumtasks", "10")
	sumtasksint, err := strconv.Atoi(sumtasks)
	if err != nil || sumtasksint <= 0 {
		appG.Response(http.StatusBadRequest, "总任务数参数格式错误", nil)
		return
	}

	unmmax := c.DefaultQuery("unmmax", "5")
	unmmaxint, err := strconv.Atoi(unmmax)
	if err != nil || unmmaxint <= 0 {
		appG.Response(http.StatusBadRequest, "最大并发数参数格式错误", nil)
		return
	}

	// 限制最大并发数不超过总任务数
	if unmmaxint > sumtasksint {
		unmmaxint = sumtasksint
	}

	// 使用context进行超时控制和取消
	ctx, cancel := context.WithTimeout(c.Request.Context(), 30*time.Second)
	defer cancel()

	sem := make(chan struct{}, unmmaxint) // 信号量通道，控制最大并发数
	var wg sync.WaitGroup
	errChan := make(chan error, 1) // 错误通道

	// 启动所有任务
	for i := 0; i < sumtasksint; i++ {
		select {
		case <-ctx.Done(): // 检查上下文是否被取消
			appG.Response(http.StatusRequestTimeout, "请求超时或被取消", nil)
			return
		case sem <- struct{}{}: // 获取信号量
			wg.Add(1)
			go func(taskNum int) {
				defer func() {
					<-sem // 释放信号量
					wg.Done()
				}()

				// 执行任务，支持上下文取消
				if err := e.concurrentTaskTWo(ctx, taskNum); err != nil {
					select {
					case errChan <- err: // 发送错误，但不阻塞
					default:
					}
				}
			}(i)
		}
	}

	// 等待所有任务完成
	done := make(chan struct{})
	go func() {
		wg.Wait()
		close(done)
	}()

	// 等待完成或超时
	select {
	case <-done:
		// 所有任务完成
		close(sem)
		appG.Response(http.StatusOK, "并发任务执行完成", gin.H{
			"total_tasks":    sumtasksint,
			"max_concurrent": unmmaxint,
			"success_tasks":  sumtasksint, // 实际应该统计成功数量
		})
	case <-ctx.Done():
		appG.Response(http.StatusRequestTimeout, "任务执行超时", nil)
	case err := <-errChan:
		appG.Response(http.StatusInternalServerError, "任务执行失败: "+err.Error(), nil)
	}
}

// 改进的并发任务方法，支持上下文取消
func (e *TestController) concurrentTaskTWo(ctx context.Context, taskNum int) error {
	select {
	case <-ctx.Done():
		return ctx.Err() // 任务被取消
	default:
		// 继续执行任务
	}

	fmt.Printf("任务 %d 开始执行\n", taskNum)

	// 模拟任务执行，但支持中断
	select {
	case <-time.After(3 * time.Second):
		// 正常执行完成
		fmt.Printf("任务 %d 执行完成\n", taskNum)
		return nil
	case <-ctx.Done():
		fmt.Printf("任务 %d 被取消\n", taskNum)
		return ctx.Err()
	}
}

// Worker Pool  模式

func (e *TestController) WorkerPool(c *gin.Context) {
	var appG = app.Gin{C: c}
	// 参数解析和验证
	sumtasks := c.DefaultQuery("sumtasks", "10")
	sumtasksint, err := strconv.Atoi(sumtasks)
	if err != nil || sumtasksint <= 0 {
		appG.Response(http.StatusBadRequest, "总任务数参数格式错误", nil)
		return
	}
	unmmax := c.DefaultQuery("unmmax", "5")
	unmmaxint, err := strconv.Atoi(unmmax)
	if err != nil || unmmaxint <= 0 {
		appG.Response(http.StatusBadRequest, "最大并发数参数格式错误", nil)
		return
	}

	//限制最大并发数量，不超过总的任务总数
	if unmmaxint > sumtasksint {
		unmmaxint = sumtasksint
	}
	//context  进行超过控制和取消
	ctx, cancel := context.WithTimeout(c.Request.Context(), 30*time.Second)
	defer cancel()

	// 创建固定数量的 worker
	//sem  := make(chan struct{}, unmmaxint)
	sem := make(chan struct{}, unmmaxint) // 信号量通道，控制最大并发数
	var wg sync.WaitGroup
	errChan := make(chan error, 1) // 错误通道

	// 启动所有任务
	for i := 0; i < sumtasksint; i++ {
		select {
		case <-ctx.Done(): //检查上下文是否被取消
			appG.Response(http.StatusRequestTimeout, "请求被取消！", nil)
			return
		case sem <- struct{}{}: // 获取信号量
			wg.Add(1)
			go func(taskNum int) {
				defer func() {
					<-sem // 释放信号量
					wg.Done()
				}()

				// 执行任务，支持上下文取消
				if err := e.concurrentTaskTWo(ctx, taskNum); err != nil {
					select {
					case errChan <- err: // 发送错误，但不阻塞
					default:
					}
				}
			}(i)
		}
	}

	//等待所有任务完成
	done := make(chan struct{})
	go func() {
		wg.Wait()
		close(done)
	}()
	//等待完成或超时

	select {
	case <-done:
		//所有任务完成
		close(sem)
		appG.Response(http.StatusOK, "并发任务执行完成", gin.H{
			"total_tasks":    sumtasksint,
			"max_concurrent": unmmaxint,
			"success_tasks":  sumtasksint,
		})
	case <-ctx.Done():
		appG.Response(http.StatusRequestTimeout, "任务执行超时", nil)
	case err := <-errChan:
		appG.Response(http.StatusInternalServerError, "任务执行失败："+err.Error(), nil)
	}
}
